#define NUM_BONES 12
#define NUM_JOINTS 11

class Bone : public cyclone::CollisionBox
{
public:
	bool atposition;
	cyclone::Vector3 chosenDestination;
	cyclone::Vector3 velocityMovement;
	cyclone::Vector3 thisExtent;
	int max_moveamount;
	int moveamount;
	bool xMinus;
	bool zMinus;
	bool chosenEnemy;
	bool BONE_COLLIDE;
	bool BONE_BOX_COLLIDE;
	int movement_direction;
	float moveXamount;
	int movementCounter;
    Bone()
    {
        body = new cyclone::RigidBody();
		atposition = true;
		chosenDestination = cyclone::Vector3(0,0,0);
		thisExtent = cyclone::Vector3(0,0,0);
		velocityMovement = cyclone::Vector3(0,0,0);
		movementCounter = 0;
		xMinus = false;
		zMinus = false;
		moveXamount = 0;
		chosenEnemy = false;
		BONE_COLLIDE = false;
		BONE_BOX_COLLIDE = false;
		movement_direction = 1;
		max_moveamount = 200;
		moveamount = 0;
    }

    ~Bone()
    {
        delete body;
    }

	int getMoveMentDirection(){return movement_direction;}
	void changeDirection(){movement_direction*=-1;}
	bool getxMinus(){
		return xMinus;
	}
	void setxMinus(bool b){
		xMinus = b;
	}

	bool getzMinus(){
		return zMinus;
	}
	void setzMinus(bool b){
		zMinus = b;
	}

	int getCounter(){
		return movementCounter;
	}
	void incredCounter(){
		movementCounter++;
	}

	void resetCounter(){
		movementCounter = 0;
	}

	bool atPosition() const{
		return atposition;
	}
	void atPosition(bool b){
		atposition = b;
	}

	cyclone::Vector3 getExtent(){
		return thisExtent;
	}

	cyclone::Vector3 getVelocity(){
		return velocityMovement;
	}

	void setVelocity(cyclone::Vector3 vel){
		velocityMovement = vel;
	}

	void atDestination(cyclone::Vector3 vec){
		chosenDestination = vec;
	}
	cyclone::Vector3 atDestination(){
		return chosenDestination;
	}
	/** 
	 * We use a sphere to collide bone on bone to allow some limited 
	 * interpenetration.
	 */
	cyclone::CollisionSphere getCollisionSphere() const
	{
		cyclone::CollisionSphere sphere;
		sphere.body = body;
		sphere.radius = halfSize.x;
		sphere.offset = cyclone::Matrix4();
		if (halfSize.y < sphere.radius) sphere.radius = halfSize.y;
		if (halfSize.z < sphere.radius) sphere.radius = halfSize.z;
		sphere.calculateInternals();
		return sphere;
	}

    /** Draws the bone. */
    void render()
    {
        // Get the OpenGL transformation
        GLfloat mat[16];
        body->getGLTransform(mat);

        if (body->getAwake()) glColor3f(0.5, 0.3, 0.3);
        else glColor3f(0.3, 0.3, 0.5);

		if(chosenEnemy)glColor3f(1, 0, 0);
		else glColor3f(0, 1, 1);

        glPushMatrix();
        glMultMatrixf(mat);
        glScalef(halfSize.x*2, halfSize.y*2, halfSize.z*2);
        glBegin(GL_QUADS);
		{
			glNormal3f( 0.0f, 0.0f, 1.0f);					// Normal Pointing Towards Viewer
			//glTexCoord2f(0.0f, 0.0f); 
			glVertex3f(-0.5f, -0.5f,  0.5f);	// Point 1 (Front)
			//glTexCoord2f(0.5f, 0.0f); 
			glVertex3f( 0.5f, -0.5f,  0.5f);	// Point 2 (Front)
			//glTexCoord2f(1.0f, 1.0f); 
			glVertex3f( 0.5f,  0.5f,  0.5f);	// Point 3 (Front)
			//glTexCoord2f(0.0f, 1.0f); 
			glVertex3f(-0.5f,  0.5f,  0.5f);	// Point 4 (Front)

			// Back Face
			glNormal3f( 0.0f, 0.0f,-1.0f);					// Normal Pointing Away From Viewer
			//glTexCoord2f(1.0f, 0.0f); 
			glVertex3f(-0.5f, -0.5f, -0.5f);	// Point 1 (Back)
			//glTexCoord2f(1.0f, 1.0f); 
			glVertex3f(-0.5f,  0.5f, -0.5f);	// Point 2 (Back)
			//glTexCoord2f(0.0f, 1.0f); 
			glVertex3f( 0.5,  0.5f, -0.5f);	// Point 3 (Back)
			//glTexCoord2f(0.0f, 0.0f); 
			glVertex3f( 0.5f, -0.5f, -0.5f);	// Point 4 (Back)

			// Top Face
			glNormal3f( 0.0f, 1.0f, 0.0f);					// Normal Pointing Up
			//glTexCoord2f(0.0f, 1.0f); 
			glVertex3f(-0.5f,  0.5f, -0.5f);	// Point 1 (Top)
			//glTexCoord2f(0.0f, 0.0f); 
			glVertex3f(-0.5f,  0.5f,  0.5f);	// Point 2 (Top)
			//glTexCoord2f(1.0f, 0.0f); 
			glVertex3f( 0.5f,  0.5f,  0.5f);	// Point 3 (Top)
			//glTexCoord2f(1.0f, 1.0f); 
			glVertex3f( 0.5f,  0.5f, -0.5f);	// Point 4 (Top)
			// Bottom Face

			glNormal3f( 0.0f,-1.0f, 0.0f);					// Normal Pointing Down
			//glTexCoord2f(1.0f, 1.0f); 
			glVertex3f(-0.5f, -0.5f, -0.5f);	// Point 1 (Bottom)
			//glTexCoord2f(0.0f, 1.0f); 
			glVertex3f( 0.5f, -0.5f, -0.5f);	// Point 2 (Bottom)
			//glTexCoord2f(0.0f, 0.0f); 
			glVertex3f( 0.5f, -0.5f,  0.5f);	// Point 3 (Bottom)
			//glTexCoord2f(1.0f, 0.0f); 
			glVertex3f(-0.5f, -0.5f,  0.5f);	// Point 4 (Bottom)
			// Right face
			glNormal3f( 1.0f, 0.0f, 0.0f);					// Normal Pointing Right
			//glTexCoord2f(1.0f, 0.0f); 
			glVertex3f( 0.5f, -0.5f, -0.5f);	// Point 1 (Right)
			//glTexCoord2f(1.0f, 1.0f); 
			glVertex3f( 0.5f,  0.5f, -0.5f);	// Point 2 (Right)
			//glTexCoord2f(0.0f, 1.0f); 
			glVertex3f( 0.5f,  0.5f,  0.5f);	// Point 3 (Right)
			//glTexCoord2f(0.0f, 0.0f); 
			glVertex3f( 0.5f, -0.5f,  0.5f);	// Point 4 (Right)
			// Left Face
			glNormal3f(-1.0f, 0.0f, 0.0f);					// Normal Pointing Left
			//glTexCoord2f(0.0f, 0.0f); 
			glVertex3f(-0.5f, -0.5f, -0.5f);	// Point 1 (Left)
			//glTexCoord2f(1.0f, 0.0f); 
			glVertex3f(-0.5f, -0.5f,  0.5f);	// Point 2 (Left)
			//glTexCoord2f(1.0f, 1.0f); 
			glVertex3f(-0.5f,  0.5f,  0.5f);	// Point 3 (Left)
			//glTexCoord2f(0.0f, 1.0f);
			glVertex3f(-0.5f,  0.5f, -0.5f);	// Point 4 (Left)        
		}
		glEnd();
        glPopMatrix();
    }

	    void renderShadow()
    {
        // Get the OpenGL transformation
        GLfloat mat[16];
        body->getGLTransform(mat);
		if(chosenEnemy)glColor3f(1, 0, 0);
		else glColor3f(0, 1, 1);

        glPushMatrix();
        glScalef(1.0f, 0, 1.0f);
        glMultMatrixf(mat);
        glScalef(halfSize.x*2, halfSize.y*2, halfSize.z*2);
        glBegin(GL_QUADS);
		{
			glVertex3f(0.5, 0.5, 0.5);  
			glVertex3f(0.5, -0.5, 0.5);  
			glVertex3f(-0.5, -0.5, 0.5); 
			glVertex3f(-0.5, 0.5, 0.5);  

			glVertex3f(0.5, 0.5, 0.5);     
			glVertex3f(0.5, 0.5, -0.5);  
			glVertex3f(0.5, -0.5, -0.5); 
			glVertex3f(0.5, -0.5, 0.5);    
		
			glVertex3f(-0.5, 0.5, -0.5);  
			glVertex3f(0.5, 0.5, -0.5);   
			glVertex3f(0.5, -0.5, -0.5);  
			glVertex3f(-0.5, -0.5, -0.5); 
		
			glVertex3f(-0.5, 0.5, 0.5);     
			glVertex3f(-0.5, 0.5, -0.5);  
			glVertex3f(-0.5, -0.5, -0.5); 
			glVertex3f(-0.5, -0.5, 0.5);    
		
			glVertex3f(-0.5, -0.5, -0.5); 
			glVertex3f(0.5, -0.5, -0.5);  
			glVertex3f(0.5, -0.5, 0.5);     
			glVertex3f(-0.5, -0.5, 0.5);    
		
			glVertex3f(-0.5, 0.5, -0.5);  
			glVertex3f(0.5, 0.5, -0.5);   
			glVertex3f(0.5, 0.5, 0.5);      		
			glVertex3f(-0.5, 0.5, 0.5);     
		}
		glEnd();
        glPopMatrix();
    }

    /** Sets the bone to a specific location. */
    void setState(const cyclone::Vector3 &position,
                  const cyclone::Vector3 &extents)
    {
        body->setPosition(position);
		body->setOrientation(cyclone::Quaternion());
		body->setVelocity(cyclone::Vector3());
        body->setRotation(cyclone::Vector3());
        halfSize = extents;
		thisExtent = extents;

        cyclone::real mass = halfSize.x * halfSize.y * halfSize.z * 8.0f;
        body->setMass(mass);

        cyclone::Matrix3 tensor;
        tensor.setBlockInertiaTensor(halfSize, mass);
        body->setInertiaTensor(tensor);

        body->setLinearDamping(0.95f);
        body->setAngularDamping(0.8f);
        body->clearAccumulators();
		body->setAcceleration(cyclone::Vector3::GRAVITY);

        body->setCanSleep(false);
        body->setAwake();

        body->calculateDerivedData();
		calculateInternals();
    }
	void setState(const cyclone::Vector3 &position,
                  const cyclone::Vector3 &extents,  const cyclone::Vector3 &velocity)
    {
        body->setPosition(position);
		body->setOrientation(cyclone::Quaternion());
		body->setVelocity(velocity);
        body->setRotation(cyclone::Vector3());
        halfSize = extents;
		thisExtent = extents;
        cyclone::real mass = halfSize.x * halfSize.y * halfSize.z * 8.0f;
        body->setMass(mass);

        cyclone::Matrix3 tensor;
        tensor.setBlockInertiaTensor(halfSize, mass);
        body->setInertiaTensor(tensor);

        body->setLinearDamping(0.95f);
        body->setAngularDamping(0.8f);
        body->clearAccumulators();
		body->setAcceleration(cyclone::Vector3::GRAVITY);

        body->setCanSleep(false);
        body->setAwake();

        body->calculateDerivedData();
		calculateInternals();
    }
};